iOS包体积优化实践 您所在的位置:网站首页 js json压缩和解压 iOS包体积优化实践

iOS包体积优化实践

2023-04-07 23:10| 来源: 网络整理| 查看: 265

_CodeSignature 文件夹: ipa 包签名文件的存放文件夹

Assets.car : Assets.xcassts 在编译过程中生成的最终展示文件,默认里面存放各种分辨率图片(测试项目未使用)

embedded.mobileprovision :证书配置文件

Info.plist :项目配置表

Plugins : App 创建的扩展,比如 Widget 、 Push 和 Share 等

.Iproj : App 所支持的语言文件

exec 文件:可执行文件,例如 widgetExtension

图片资源: .png,.jpg,.webp,.gif

其它资源文件

.xml,.json

.plist :项目中使用资源的 .plist 文件

.bundle : Mac OS 下的资源包集合

.conf :相关的配置文件

.cer , .der , .p12 :钥匙串文件

.wav :音频文件

.js , .html

.nib : Xcode 自带的数据文件,包含一个窗口程序和应用程序委托对象

.sqlite :数据库文件

.txt :文本文件

.mom : Xcode 创建的数据模型文件

.xml,.json

.plist :项目中使用资源的 .plist 文件

.bundle : Mac OS 下的资源包集合

.conf :相关的配置文件

.cer , .der , .p12 :钥匙串文件

.wav :音频文件

.js , .html

.nib : Xcode 自带的数据文件,包含一个窗口程序和应用程序委托对象

.sqlite :数据库文件

.txt :文本文件

.mom : Xcode 创建的数据模型文件

这次测试之前 IPA 未解压的大小是 76.5MB ,解压之后的大小是 140.1MB

解压后各个部分大小的明细如下

内容 大小 _CodeSignature 1.8MB Assets.car (部分使用) 518KB embedded.mobileprovision 55KB Info.plist 16KB Plugins 2.7MB Iproj 2KB exec 104.9MB 图片资源( .png,.jpg,.webp,.gif ) 16.7MB others 13.4MB

优化策略

上述了解完了 IPA 各个组成之后,我们按照 Xcode 编译优化,资源文件优化以及代码优化的顺序来一步一步进行分析

Xcode 编译优化

这个部分是最容易的,也是最容易忽略的,下面是笔者进行的总结,我们一个一个分析

编译指令集

首先查看我们目前的架构组成

augus@MacBookPro xxx.app % lipo -info xxx

Architectures inthe fat file: sohunews are: armv7 arm64

我们再看下各个架构指令集对应的机型

# armv6: iPhone, iPhone 3G, iPod 1G/2G

# armv7: iPhone 3GS, iPhone 4, iPhone 4S, iPod 3G/4G/5G, iPad, iPad 2, iPad 3, iPad Mini

# armv7s: iPhone 5, iPhone 5c, iPad 4

# arm64: iPhone X,iPhone 8(Plus),iPhone 7(Plus),iPhone 6(Plus),iPhone 6s(Plus), iPhone 5s, iPad Air(2), Retina iPad Mini(2,3)

# arm64e: XS/XS Max/XR/ iPhone 11, iPhone 11 pro,iPhone 11 Pro Max,iPhone SE (2nd generation),iPhone 12 mini,iPhone 12,iPhone 12 Pro,iPhone 12 Pro Max,Phone 13 mini,Phone 13,iPhone 13 Pro,iPhone 13 Pro Max

# x86_64: 模拟器64位处理器

# i386: 模拟器32位处理器

此次测试中我们是不需要32位架构 armv7 的,所以我们可以设置在打包的时候进行只打 armv64 即可。

方法1: Build Settings - Architectures ,把你需要的打包标识符下的设置为 arm64 ; Architectures 指定工程可以编译出多个指令集的代码包, ipa 就会变大;

方法2: Build Settings - Excluded Arcitectures ,在你要的打包标识符下面增加两个配置项目 Any iOS SDK 和 Any iOS Simulator SDK ,然后分别设置为 armv7 和 arm64 ;这个选项的意思是 Release 模式下针对真机 armv7 指令集排除,针对模拟器把 arm64 排除。

这个优化之后, ipa 压缩包大小为 51.4MB ,解压缩包大小变为 90.9MB ,其中 exec 变为 56.6MB ,效果很明显

代码优化

Build Settings - Optimization Level 在发布模式设置为 [-Oz] ,其他模式根据场景进行选择,具体参考官方文档(https://help.apple.com/xcode/mac/11.4/#/itcaec37c2a6)进行设置;这个设置指的是生成的代码在速度和二进制大小方面的优化程度

Optimization Level 默认是 -Os , -Oz 是 Xcode 11 新增的编译优化选项,该设置通过将重复的代码模式隔离到编译器生成的函数中来实现额外的尺寸节省

以下是不同的选项对应的编译速度和二进制文件大小变化趋势,来源于WWDC2019 Session 409 https://developer.apple.com/videos/play/wwdc2019/409/

优化完成之后 ipa 大小是 51MB ,解压缩包大小是 87.9MB

资源目录优化

Build Settings - Asset Catalog Compiler Options - Optimization 设置为 space ;这个选项可以改变 actool 在构建 Assets.car 时选取的编码压缩算法,减少包大小。

使用以下命令检查 Assets.car 中图片的编码压缩算法

# 可以把对应信息生成.json文件,用于对比不同

xcrun --sdk iphoneos assetutil --info Assets.car > Assets.json

项目之前用的是默认配置,由于 Assets.car 存放了少量资源,大部分都是存放在项目的根目录;

优化之后的 ipa 包大小是 51.3MB ,解压缩包大小是 90.8MB , Assets.car 大小是 469KB

调试符号

Build Settings - Generate Debug Symbols 设置为 NO ;这个选项的意思是是否在源文件编程成 .o 文件时,添加编译参数 -g 和 -gmodule ,就是 generate complete debug info ,所以产生的 .o 会变大,从而最终的可执行文件也就会变大。

需要注意的是,如果设置为 NO ,在 Xcode 中设置断点不会中断,不能进行断点调试。且最后不能生成 dSYM 文件,即使 Debug Infomation Format 设置了,也无法生成,因为生成的前提是得有调试信息,建议不要设置。

无用符号

Build Settings - Deployment Postprocessing ,调试模式下 NO ,发布模式下 YES

Deployment Postprocessing 是 Strip 的总开关 。也就是说,只有 Deployment Postprocessing 这里设置了 YES , Strip Debug Symbols During Copy 和 Strip Linked Product 设置为 YES 才会生效,其余情况均不生效

Strip Linked Product :对最终的二进制文件是否进行去除无用符号

Strip Debug Symbols During Copy :文件拷贝编译阶段是否进行 strip ,设置为 YES 之后,会把拷贝进项目的第三方库、资源或者 Extension 的调试符号剥离

Strip Linked Product :对最终的二进制文件是否进行去除无用符号

Strip Debug Symbols During Copy :文件拷贝编译阶段是否进行 strip ,设置为 YES 之后,会把拷贝进项目的第三方库、资源或者 Extension 的调试符号剥离

这个优化之后, ipa 压缩包大小为 51.4MB ,解压缩包大小变为 90.9MB ,其中 exec 变为 56.6MB ,之前已经开启,所以无变化

第三个关于符号的优化是 Build Settings - Symbols Hidden by Default ,调试模式下为 NO ,发布模式下为 YES 。该选项的意思是当启用时,所有的符号多被声明为私有的 extern ,除非在代码中使用 attribute((visibility("default"))) 明确标记为导出;反之,则所有符号都会被导出。

该测试项目中已开启,包大小无变化

复用字符串

Build Settings - Make Strings Read-Only 设置为 YES ;就是复用字符串字面。

该测试项目中已开启,包大小无变化

无效代码

Build Settings - Dead Code Stripping 设置为 YES ;是否消除无用代码

该测试项目中已开启,包大小无变化

异常捕获机制

Build Settings -搜索 exceptions

如果想要对项目瘦身,需要对途中的绿色未知设置为 NO

Enable C++ Exceptions 和 Enable Objective-C Exceptions 是指项目对错误的异常处理,比如 try catch, throw 之类的语句;所以如果你的项目中有类似的处理,关闭这个之后会报错 Cannot use '@try' with Objective-C exceptions disabled 。如果宏定义有 try ,关闭之后也会报错

如果你的项目中可以设置关闭捕获异常的开关,还需要另外设置 Build Settings - Other Link Flags 去添加一个字段

-fno-exceptions 代表禁用异常机制,参考这里:

http://gcc.gnu.org/onlinedocs/gcc-4.7.0/libstdc++/manual/manual/using_exceptions.html

现在来总结下编译优化

编译选项 _CodeSignature Assets.car embedded.mobileprovision Info.plist Plugins Iproj exec 图片资源 others ipa 解压缩包 初始配置 1.8MB 518KB 55KB 16KB 2.7MB 2KB 104.9MB 16.7MB 13.4MB 76.5MB 140.1MB Architectures 1.8MB 518KB 55KB 17KB 1.8MB 2KB 56.6MB 16.7MB 12.6MB 51.4MB 90.1MB Optimization 1.8MB 469KB 55KB 17KB 1.8MB 2KB 56.6MB 16.7MB 13.4MB 51.3MB 90.8MB Optimization Level 1.8MB 469KB 55KB 17KB 1.8MB 2KB 53.6MB 16.7MB 13.5MB 51MB 87.9MB

资源文件优化

资源文件的优化就相对比较简单,但是比较繁琐;与上面的 Xcode 编译配置不同,一次设置永久有效,资源的优化需要平时开发就需要关注,比如新资源的压缩,无用资源的删除等。

资源文件优化大体分为两个方向,第一个就是无用资源的删除,第二个就是已用资源的压缩。这里建议分先后顺序,就是先做删除,后做压缩,因为如果反过来,就会做一些无用功。

无用资源的删除

已定义未使用的代码文件

已废弃的业务,代码还在

已引用的图片但未使用

某些重复资源的导入

已定义未使用的代码文件

已废弃的业务,代码还在

已引用的图片但未使用

某些重复资源的导入

已用资源的优化

项目中引入的图片、网页、音频等文件的压缩

项目中引入的图片、网页、音频等文件的压缩

随着项目的迭代,每个项目都会或多或少存在冗余。可能是已经下线的业务,但是没人通知开发,于是代码逻辑一直存在;可能是删除某业务代码的时候,对应的图片资源为删除;又或者是多个开发导入了相同功能的第三方库。

对于这部分的优化分为预防和治理

关于预防

个人认为首先要有规范的流程,按流程执行,减少信息不对等的情况出现

产品和开发,广告和开发,都会导致相关业务的冗余,产品知道具体的业务数据,而开发不知道,所以通过某个固定时间的一次集中同步,让开发可以了解到自己的业务是否活跃,从而对项目进行相应的调整。

开发与开发之间的消息不对等,会导致各自开发自己的轮子,重复造轮子,所以可以通过建立公共文档、开发流程规范、项目使用第三方库规范、设计规范、代码规范都一一列举出来,每个人都能根据对应的文档了解到对应项目的信息,每个人开发都应该有一套统一的标准,这样就很大程度上避免了一人一套代码问题的出现。

具体规范流程可以根据自己公司或自己部分的实际情况来,多问为什么,比如这样

为什么会有类似的情况出现?

出现之后是否有处理?

怎么才能避免类似的事再次出现?

为什么会有类似的情况出现?

出现之后是否有处理?

怎么才能避免类似的事再次出现?

如果你的项目代码在百万级以下,推荐你使用 AppCode 来静态检查无用代码,如果超过了百万的团队,一般会自己通过 Clang 静态分析来开发工具,去检查无用的代码和类

使用 AppCode 做分析很简单,直接使用 AppCode 打开你需要检查的工程,等待索引建立完成,点击顶部菜单的 Code - Inspect Code

然后选择扫描范围,默认是整个工程,可以自定义

然后等待静态分析完成即可,完成之后就会控制台显示 Unused code 的提示

下面说下无用代码的类型

内容 中文翻译 Unused class 无用类 Unused global declaration 无用的全局声明 Unused import statement 无用的类引入声明 Unsed instance variable 无用的实例变量 Unused local variable 无用的局部变量 Unused macro 无用的宏 Unused method 无用的方法 Unused parameter 无用的参数 Unused property 无用的属性 Unused value 无用的值

虽然 AppCode 完成了大部分的工作,但是还是有一些问题存在,下面是我测试总结的问题

JSONModel 定义了未使用协议会被判定为无用协议

如果子类使用了父类的方法,父类的这个方法会判断为未使用

通过点语法使用属性,该属性会被认为未使用

使用 performSelector 方式调用的方法检查不出来,比如 [self performSelector:@selector(fetchPhotos:)] ,会认为 fetchPhotos: 是未使用

运行时声明的类也检查不出来,比如通过 NSClassFromString 方式调用的类会被查出未使用

JSONModel 定义了未使用协议会被判定为无用协议

如果子类使用了父类的方法,父类的这个方法会判断为未使用

通过点语法使用属性,该属性会被认为未使用

使用 performSelector 方式调用的方法检查不出来,比如 [self performSelector:@selector(fetchPhotos:)] ,会认为 fetchPhotos: 是未使用

运行时声明的类也检查不出来,比如通过 NSClassFromString 方式调用的类会被查出未使用

// or

[[ selfclass] getPhotos];

基于上述的原因,我们需要人工二次确认才能够安全删除代码,虽然繁琐,但是很安全。

已废弃业务,代码还在

定期对业务流程进行梳理,结合综合业务数据的埋点,同产品和广告确认功能是否已经下线,从而决定是否移除对应的业务模块

已引入未使用的图片

这里我测试使用的是 LSUnusedResources (https://github.com/tinymind/LSUnusedResources),针对使用编号规则的图片来说,可以直接添加规则来处理,使用也很简单;建议在删除前在项目中进行二次全局搜索确认,是否确实没有使用

某些重复资源的导入

重复资源分为静态库和项目文件

针对静态库,有多个相似功能进行需求整合,把最优解决方案的静态库留下,其余的跟相关产品和广告人员进行移除确认,比如线上崩溃采集听云、 bugly 和 matrix 等

针对项目文件,可以使用 fdupes 工具进行重复文件扫描,该工具的原理是通过校验所有的资源的 MD5 值,筛选出项目中重复的资源,文件比较顺序是

文件大小 > 部分 MD5 签名对比 > 完整 MD5 签名对比 > 逐字节对比

文件大小 > 部分 MD5 签名对比 > 完整 MD5 签名对比 > 逐字节对比

fdupes 的安装和使用

# Searches the given path for duplicate files. Such files are found by

# comparing file sizes and MD5 signatures, followed by a byte-by-byte comparison.

# install fdupes

$ brew install fdupes

# where xxx is the directory to be scanned, and xxxFdupesResult.txt is the output file of the scan result

$ fdupes -Sr /User/augus/Documents/xxx > /User/augus/Documents/xxxFdupesResult.txt

已用资源的优化

已用资源的优化主要是就是图片、网页、 json 、音频文件的压缩

网页的压缩,是放入 App 资源中的 js 或者 html 文件,最好是经过 H5 端压缩后的

json 文件的压缩,如果不是即时使用的,可以放倒云端或者后台,进行网络获取后使用

音频的压缩,需要跟产品和广告进行沟通,在可接受范围内,选择系统可支持的压缩比最高的格式

最后说图片的压缩,分为以下几个部分

如果图片小于 100KB 则使用 TinyPng 进行再一步压缩,使用 TinyPng 压缩三次即可达到极限值;这里推荐一个 TinyPng 的多图压缩的脚本(https://github.com/mokong/BatchProcessImage),因为在线最多一次最多20张,原理就是封装了官方的一个压缩接口,通过一个邮箱注册一个key,然后每个 key 就是500次/月。

将图片放入 xcassets ,因为 xcassets 里的 @2x 和 @3x 图片,在上传时,会根据具体设备分开对应分辨率的图片,不会同时包含。而放入 .bundle 中的都会包含,所以要尽量把图片放入 xcassets 中。 Assets.car 编译过程中有时会选择一些图片,拼凑成一张大图来提高图片的加载效率。被放进这张大图的小图会变为通过偏移量的引用,建议使用频率高且小的图片放到 xcassets 中, xcassets 能保证加载和渲染速度最优。

大于 100KB 就不要放入 xcassets 中了。大的图片可以考虑将图片转成WebP。WebP是Google公司的一个开源项目,能够把图片压缩到很小,但是肉眼看不出来差别,目前 iOS 常用的图片显示类库都支持该格式解析的拓展。 可使用鹅厂的一个工具iSparta (http://isparta.github.io/)进行批量转换。

如果图片小于 100KB 则使用 TinyPng 进行再一步压缩,使用 TinyPng 压缩三次即可达到极限值;这里推荐一个 TinyPng 的多图压缩的脚本(https://github.com/mokong/BatchProcessImage),因为在线最多一次最多20张,原理就是封装了官方的一个压缩接口,通过一个邮箱注册一个key,然后每个 key 就是500次/月。

将图片放入 xcassets ,因为 xcassets 里的 @2x 和 @3x 图片,在上传时,会根据具体设备分开对应分辨率的图片,不会同时包含。而放入 .bundle 中的都会包含,所以要尽量把图片放入 xcassets 中。 Assets.car 编译过程中有时会选择一些图片,拼凑成一张大图来提高图片的加载效率。被放进这张大图的小图会变为通过偏移量的引用,建议使用频率高且小的图片放到 xcassets 中, xcassets 能保证加载和渲染速度最优。

大于 100KB 就不要放入 xcassets 中了。大的图片可以考虑将图片转成WebP。WebP是Google公司的一个开源项目,能够把图片压缩到很小,但是肉眼看不出来差别,目前 iOS 常用的图片显示类库都支持该格式解析的拓展。 可使用鹅厂的一个工具iSparta (http://isparta.github.io/)进行批量转换。

WebP在CPU消耗和解码时间上会比PNG高2倍,所以我们要在性能和体积上做取舍

监控机制

优化完成之后,如何保证包大小不会再次迅速增大?或者如何迅速定位增大原因,就需要依赖一套合适的监控机制和合理的流程规范来保证。

监控机制保证实时发现问题,每次打包完成后,运行脚本比较包大小差异,如果有增大超过了设置的阈值,则邮件通知相关负责人,负责人排查原因,同时做好记录;每次打包的包大小进行文档记录,造成包大小变化的原因记录

流程规范是用于保证每个项目开发者在开发中有良好的开发习惯,避免包大小突然增大,而一无所知

引入新的第三方库,要考虑项目中是否有相同类型的,是否可以自己实现,是否会造成体积增大

新增图片资源,关注大小,是否能用代码实现,进行适当压缩

及时清理废弃模块

每次打包关注包大小变化,文档记录,持续跟踪

引入新的第三方库,要考虑项目中是否有相同类型的,是否可以自己实现,是否会造成体积增大

新增图片资源,关注大小,是否能用代码实现,进行适当压缩

及时清理废弃模块

每次打包关注包大小变化,文档记录,持续跟踪

包大小不是一时可以完成,需要平时每个相关人都去注意,有了良好的开发规范,开发流程就能持续进行改进,从而达到一个平衡稳定状态。

参考文档

Build Setting Reference https://help.apple.com/xcode/mac/11.4/#/itcaec37c2a6

包体积大小:瘦身 https://www.zybuluo.com/qidiandasheng/note/1662385)

抖音品质建设 - iOS 安装包大小优化实践篇 https://blog.csdn.net/ByteDanceTech/article/details/112504772

Build Setting Reference https://help.apple.com/xcode/mac/11.4/#/itcaec37c2a6

包体积大小:瘦身 https://www.zybuluo.com/qidiandasheng/note/1662385)

抖音品质建设 - iOS 安装包大小优化实践篇 https://blog.csdn.net/ByteDanceTech/article/details/112504772

-End-

最近有一些小伙伴,让我帮忙找一些 面试题 资料,于是我翻遍了收藏的 5T 资料后,汇总整理出来,可以说是程序员面试必备! 所有资料都整理到网盘了,欢迎下载!

面试题】即可获取

在看点这里好文分享给更多人↓↓ 返回搜狐,查看更多



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有